<?php

namespace App\Custom\Api;

use Illuminate\Http\Resources\Json\ResourceCollection;
use Symfony\Component\HttpFoundation\Response as FoundationResponse;

trait ApiResponse
{
    /**
     * @var int
     */
    protected $statusCode = FoundationResponse::HTTP_OK;

    /**
     * @var array
     */
    protected $metadata = [];

    /**
     * @return int
     */
    public function getStatusCode()
    {
        return $this->statusCode;
    }

    /**
     * @param $statusCode
     * @return $this
     */
    public function setStatusCode($statusCode)
    {
        $this->statusCode = $statusCode;
        return $this;
    }

    /**
     * @param $data
     * @param $header
     * @return \Illuminate\Http\JsonResponse
     */
    public function respond($data, $header = [])
    {
        return response()->json($data, $this->getStatusCode(), $header);
    }

    /**
     * @param       $status
     * @param array $data
     * @param null  $code
     * @param null  $meta
     * @return \Illuminate\Http\JsonResponse
     */
    public function status($status, array $data, $code = null, $meta = null)
    {
        if ($code){
            $this->setStatusCode($code);
        }

        $status = [
            'status' => $status,
            'code' => $this->statusCode
        ];

        // 代表分页
        if ( $meta ) {
            $status['meta'] = $meta;
        }

        $data = array_merge($status, $data);

        return $this->respond($data);
    }

    /**
     * @param        $message
     * @param int    $code
     * @param string $status
     * @param array  $extend
     * @return \Illuminate\Http\JsonResponse
     */
    public function failed($message, $code = FoundationResponse::HTTP_BAD_REQUEST, $extend = [], $status = 'error')
    {
        return $this->setStatusCode($code)->message($message, $extend, $status);
    }

    /**
     * @param        $message
     * @param string $status
     * @param array  $extend
     * @return \Illuminate\Http\JsonResponse
     */
    public function message($message, $extend = [], $status = "success")
    {
        $data = array_merge(['message' => $message], $extend);

        return $this->status($status, $data);
    }

    /**
     * @param string $message
     * @return \Illuminate\Http\JsonResponse
     */
    public function internalError($message = "Internal Error!"){
        return $this->failed($message, FoundationResponse::HTTP_INTERNAL_SERVER_ERROR);
    }

    /**
     * @param string $message
     * @return \Illuminate\Http\JsonResponse
     */
    public function created($message = "created")
    {
        return $this->setStatusCode(FoundationResponse::HTTP_CREATED)
            ->message($message);
    }

    /**
     * @param $data
     * @param string $status
     * @param string $code
     * @return \Illuminate\Http\JsonResponse
     */
    public function success($data, $status = "success", $code = null)
    {
        if ($data instanceof ResourceCollection) {
            try {
                $data->currentPage();
                return $this->paginator($data, $status);
            } catch (\Exception $e) {}
        }

        if (!empty($this->metadata)) {
            return $this->status($status, compact('data'), $code, $this->metadata);
        }

        return $this->status($status, compact('data'), $code);
    }

    /**
     * @param array $metadata
     * @return $this
     */
    public function meta(array $metadata)
    {
        $this->metadata = $metadata;
        return $this;
    }

    /**
     * @param $data
     * @param string $status
     * @return \Illuminate\Http\JsonResponse
     */
    public function paginator($data, $status = "success")
    {
        $meta = [
            'pagination' => [
                "total" => (int) $data->total(),
                "count" =>  (int) $data->count(),
                "per_page" =>  (int) $data->perPage(),
                "current_page" => (int) $data->currentPage(),
                "total_pages" =>  (int) $data->lastPage()
            ]
        ];
        if ($data->additional) {
            foreach ($data->additional as $key => $add) {
                $meta[$key] = $add;
            }
        }
        if (!empty($this->metadata)) {
            $meta = array_merge($this->metadata, $meta);
        }
        return $this->status($status, compact('data'), null, $meta);
    }

    /**
     * @param string $message
     * @return \Illuminate\Http\JsonResponse
     */
    public function notFond($message = 'Not Fond!')
    {
        return $this->failed($message, Foundationresponse::HTTP_NOT_FOUND);
    }
}
